package org.unidata.mdm.dq.core.service.impl.instance;

import java.util.Objects;
import java.util.Set;

import org.unidata.mdm.core.type.model.instance.AbstractNamedDisplayableImpl;
import org.unidata.mdm.dq.core.type.cleanse.CleanseFunctionConfiguration.CleansePortConfiguration;
import org.unidata.mdm.dq.core.type.cleanse.CleanseFunctionPortFilteringMode;
import org.unidata.mdm.dq.core.type.cleanse.CleanseFunctionPortInputType;
import org.unidata.mdm.dq.core.type.cleanse.CleanseFunctionPortValueType;
import org.unidata.mdm.dq.core.type.model.instance.PortElement;
import org.unidata.mdm.dq.core.type.model.source.CleanseFunctionPort;

/**
 * @author Mikhail Mikhailov on Feb 5, 2021
 */
public class PortImpl extends AbstractNamedDisplayableImpl implements PortElement {
    /**
     * Constructed from user supplied configuration.
     */
    protected final CleanseFunctionPort portSource;
    /**
     * Constructed from function autoconfiguration.
     */
    protected final CleansePortConfiguration portConfig;
    /**
     * Constructor.
     * @param name
     * @param displayName
     */
    PortImpl(CleanseFunctionPort port) {
        super(port.getName(), port.getDisplayName(), port.getDescription());
        this.portSource = port;
        this.portConfig = null;
    }
    /**
     * Constructor.
     * @param config
     */
    PortImpl(CleansePortConfiguration config) {
        super(config.getName(), config.getDisplayName(), config.getDescription());
        this.portSource = null;
        this.portConfig = config;
    }

    private boolean isSourceConfig() {
        return Objects.nonNull(portSource);
    }

    private boolean isAutoConfig() {
        return Objects.nonNull(portConfig);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getName() {
        return isAutoConfig() ? portConfig.getName() : super.getName();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public String getDisplayName() {
        return isAutoConfig() ? portConfig.getDisplayName() : super.getDisplayName();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public String getDescription() {
        return isAutoConfig() ? portConfig.getDescription() : super.getDescription();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isRequired() {

        if (isSourceConfig()) {
            return portSource.isRequired();
        } else if (isAutoConfig()) {
            return portConfig.isRequired();
        }

        return false;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public CleanseFunctionPortFilteringMode getFilteringMode() {

        CleanseFunctionPortFilteringMode m = null;
        if (isSourceConfig()) {
            m = portSource.getFilteringMode();
        } else if (isAutoConfig()) {
            m = portConfig.getFilteringMode();
        }

        return m == null ? CleanseFunctionPortFilteringMode.MODE_UNDEFINED : m;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public Set<CleanseFunctionPortInputType> getInputTypes() {

        if (isSourceConfig()) {
            return portSource.getInputTypes();
        } else if (isAutoConfig()) {
            return portConfig.getInputTypes();
        }

        return null;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public Set<CleanseFunctionPortValueType> getValueTypes() {

        if (isSourceConfig()) {
            return portSource.getValueTypes();
        } else if (isAutoConfig()) {
            return portConfig.getValueTypes();
        }

        return null;
    }
}
